/*

    file:   config_hw.h
    desc:   Global hardware configuration file.

    author: Jaromir Dvorak (md@unicode.cz)

    This file is part of the AVGA platform.
    http://avga.prometheus4.com/


    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

*/

#ifndef _CONFIG_HW_
#define _CONFIG_HW_


/*
 *
 *  VIDEO SYNC GENERATOR hardware configuration
 *
 */

#define VIDEO_HWCONFIG

//
// Sync generator needs one full AVR 16-bit timer/counter with PWM.
// configured here for TIMER1, atmega168.
//
#define VIDEO_TIMER_CMP_IRQ         TIMER1_COMPA_vect
#define VIDEO_TIMER_OVF_IRQ         TIMER1_OVF_vect
#define VIDEO_TIMER_OCRA            OCR1A
#define VIDEO_TIMER_OCRB            OCR1B
#define VIDEO_TIMER_ICR             ICR1
#define	VIDEO_TIMER_OCRB_DDR        DDRB	//hsync DDR
#define VIDEO_TIMER_OCRB_PIN        2		//hsync PIN
#define	VIDEO_VSYNC_DDR		        DDRB	//vsync DDR
#define VIDEO_VSYNC_PIN     		1		//vsync PIN
#define	VIDEO_VSYNC_PORT	        PORTB	//vsync PORT


//
// Setting up the timer: fast PWM, no prescaling, OCRB connected to SYNC.
//
#define __video_timer_select_OVF_IRQ()      TIMSK1 = 1 << TOIE1
#define __video_timer_select_CMP_IRQ()      TIMSK1 = 1 << OCIE1A
#define	__video_timer_clear_OVF_IRQ()       TIFR1 = 0xFF
#define __video_timer_clear_CMP_IRQ()       TIFR1 = 0xFF
#define __video_timer_setup_mode14()							\
	TCCR1A = 1 << WGM11 | 0 << WGM10 | 1 << COM1B1 | 1 << COM1B0;			\
	TCCR1B = 1 << WGM13 | 1 << WGM12 | 0 << CS12 | 0 << CS11 | 1 << CS10;

//
// Scan-line interrupt will occur between 2 instructions.
// Since not all AVR instructions take only one cycle, precission sync is needed to avoid jitter.
// 16-bit PC (<=64k) AVR devices have instructions with maximum of four clock cycles.
// This macro synchronises the callers program flow with video timer (modulo 4 = 0).
// We must also consider few cycles waiting to do the sync at right time,
// depending on amount of cycles consumed by C code since interrupt occured.
// configured here for TIMER1, atmega168.
//

/*
#define VIDEO_TIMER_FINE_SYNC()					\
asm volatile("rjmp .  					\r\n	\
			  lds __tmp_reg__, %0		\r\n	\
			  sbrs __tmp_reg__, 0		\r\n	\
			  rjmp .					\r\n 	\
			  sbrs __tmp_reg__, 1		\r\n	\
			  lpm __tmp_reg__, Z		\r\n"	: : "M" (_SFR_MEM_ADDR(TCNT1L)))
*/

//
// Simple version. Does only 0/1 cycle sync. It will work properly only when all the lines are scanned
// during the blocking call of video_sync() function, becouse only one and two cycle instructions are used there.
//

#define VIDEO_TIMER_FINE_SYNC()					\
asm volatile("lds __tmp_reg__, %0		\r\n	\
			  sbrs __tmp_reg__, 0		\r\n	\
			  rjmp .					\r\n"  : : "M" (_SFR_MEM_ADDR(TCNT1L)))


/*
 *
 *  GRAPHICS DRIVER hardware configuration
 *
 */

#define DRIVER_HWCONFIG

//
// Video bitstream will apear at upper 4 bits of this port. lower 4 bits can be used as input.
//
#define VIDEO_PORT              PORTD
#define VIDEO_DDR               DDRD
#define VIDEO_DEFAULT_DDR	0x08	//default DDR mask


/*
 *
 *  SOUND DRIVER hardware configuration
 *
 */

#define SOUND_HWCONFIG

//
// audio output port
//
#define SOUND_TIMER_PORT		PORTD
#define SOUND_TIMER_DDR			DDRD
#define SOUND_TIMER_DDR_PIN		3

//
// audio timer setup
//
// configured here for TIMER2, ATMega168
//
// Note: The m168 8bit timer version has two output pins. We use one value for TOP (OCR2A)
// and the second (OCR2B) as compare value set to 1 in CTC mode. So if OCR2A is set to 0,
// there is no output at OCR2B pin (no sound) without the need of stopping the timer at all.
//
#define __sound_init_timer()	OCR2B = 1; 	TCCR2A = 0x12;	TCCR2B = 0x05;

#define __sound_set_timer(a) ({ OCR2A = a; })

#define __sound_stop_timer()    OCR2A = 0


//
// example for 8bit timers with only one output pin

//#define __sound_init_timer()
//#define __sound_set_timer(a) ({ OCR2 = a; if(a) TCCR2 = 0x1D; else TCCR2 = 0; })
//#define __sound_stop_timer()    TCCR2 = 0


#endif




